﻿using QxFramework.Utilities;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapManager : MonoSingleton<MapManager>, IEventListener
{
    //public GameObject Dice;
    public GameObject Map;
    public GameObject DicePrefab;
    public GameObject CubePrefab;
    public GameObject SurfacePrefab;
    public GameObject SpawnCube;

    //public GameObject Dice;
    public List<string> DicePrefabname = new List<string>() { "Dice_1", "Dice_2", "Dice_3", "Dice_4", "Dice_5", "Dice_6" }; public bool Time2CheckIt; private static readonly List<Vector3> Axises = new List<Vector3> { Vector3.right, Vector3.left, Vector3.up, Vector3.down, Vector3.forward, Vector3.back };
    private static readonly Dictionary<Vector3, Quaternion> QuaternionsOuter = new Dictionary<Vector3, Quaternion>()
    {
        { Axises[0], Quaternion.Euler(-90,0,-90) },
        { Axises[1], Quaternion.Euler(-90,0,90) },
        { Axises[2], Quaternion.Euler(0,0,0) },
        { Axises[3], Quaternion.Euler(-180,0,0) },
        { Axises[4], Quaternion.Euler(-90,0,180) },
        { Axises[5], Quaternion.Euler(-90,0,0) }
    };
    private static readonly Dictionary<Vector3, Quaternion> QuaternionsInner = new Dictionary<Vector3, Quaternion>()
    {
        { Axises[1], Quaternion.Euler(-90,0,-90) },
        { Axises[0], Quaternion.Euler(-90,0,90) },
        { Axises[3], Quaternion.Euler(0,0,0) },
        { Axises[2], Quaternion.Euler(-180,0,0) },
        { Axises[5], Quaternion.Euler(-90,0,180) },
        { Axises[4], Quaternion.Euler(-90,0,0) }
    };

    public List<DiceData> Dices2Flip = new List<DiceData>();
    private SurfaceData SurfacePlayerAtWhenFlip;

    private List<string> BlockArray = new List<string> { "null", "Block/Tree_2", "Block/Tree_3", "Block/Tree_4" };
    private List<string> EnemyArray = new List<string> { "Enemy/Snake", "Enemy/Spider", "null", "null" };
    private List<string> PropArray = new List<string> { "Prop/Key", "Prop/Knife", "Prop/Shoushi", "Prop/Treasure" };

    private List<object> Items = new List<object>();
    //private List<> ItemPrefab=new List<List>()

    private void Awake()
    {
        Items.Add(BlockArray);
        Items.Add(EnemyArray);
        Items.Add(PropArray);
        //DicePrefab = Resources.Load("Dice/"+DicePrefabname[i]) as GameObject;
        CubePrefab = Resources.Load("Cube") as GameObject;
        SurfacePrefab = Resources.Load("Surface") as GameObject;
        SpawnCube = Resources.Load("SpawnCube") as GameObject;
        Map = gameObject;
        Time2CheckIt = false;

    }

    private void OnDestroy()
    {
        EventNodeCore.GetInstance().DetachEventListener(EventDef.FlipTurn, this);
        EventNodeCore.GetInstance().DetachEventListener(EventDef.FlipCheckTurn, this);
    }

    private void Start()
    {
        EventNodeCore.GetInstance().AttachEventListener(EventDef.FlipTurn, this);
        EventNodeCore.GetInstance().AttachEventListener(EventDef.FlipCheckTurn, this);
    }

    public int EventPriority() { return 0; }

    public bool HandleEvent(int id, object param1, object param2)
    {
        //if (id == EventDef.DiceSpawn)
        //{
        //    GroundCoordinate currentDice = (GroundCoordinate) param1;
        //    ///当前位置
        //    Vector3 position = currentDice.DiceCoordinate;
        //    position = new Vector3(position.x, position.y, position.z + 1);
        //    StartCoroutine(SpawnMap(position));

        //}
        switch (id)
        {
            case EventDef.FlipCheckTurn:
                //EventNodeCore.GetInstance().SendMessage(EventDef.GroundStateChange, null);
                CheckFlip();
                break;
            case EventDef.FlipTurn:
                FlipAct();
                break;
        }
        return false;
    }



    /// <summary>
    /// 生成地图，同时生成多个方块时使用。
    /// </summary>
    /// <param name="indexs"></param>
    public void SpawnMap(List<Vector3> indexs)
    {
        for (int i = 0; i < indexs.Count; i++)
        {
            CreatCube(indexs[i]);
        }
    }
    /// <summary>
    /// 生成方块 TODO 将Instantiate改为从对象池取出
    /// </summary>
    /// <param name="pos"></param>
    public void CreatCube(Vector3 pos)
    {
        if (!MapData.Instance.Cubes.ContainsKey(pos))
        {
            GameObject cube = Instantiate(CubePrefab, pos, Quaternion.identity, Map.transform);
            if (!cube.GetComponent<CubeController>())
            {
                cube.AddComponent<CubeController>();
            }
            CreatSurface(cube.GetComponent<CubeController>().Data);
        }
        else Debug.LogError("该方块已存在！" + pos);
    }
    /// <summary>
    /// 生成面 TODO 将Instantiate改为从对象池取出
    /// </summary>
    /// <param name="cube"></param>
    public void CreatSurface(CubeData cube)
    {
        List<Vector3> axises = new List<Vector3>(Axises.ToArray());
        List<Vector3> nearBy = new List<Vector3>();
        List<Vector3> nearDir = new List<Vector3>();

        for (int i = 0; i < axises.Count; i++)
        {
            if (MapData.Instance.Cubes.ContainsKey(cube.Index + axises[i] * 3))
            {
                nearBy.Add(cube.Index + axises[i] * 3);
                Vector3 temp;
                int x = 0, y = 0, z = 0;
                if (axises[i].x.GetHashCode() != 0.GetHashCode()) x = -(int)axises[i].x;
                else if (axises[i].y.GetHashCode() != 0.GetHashCode()) y = -(int)axises[i].y;
                else z = -(int)axises[i].z;
                temp = new Vector3Int(x, y, z);
                nearDir.Add(temp);
                axises.Remove(axises[i]);
            }
        } // 求出需要生成面的方向、相邻方块坐标和相邻方块对应的面方向

        for (int i = 0; i < axises.Count; i++)
        {
            GameObject suf = Instantiate(SurfacePrefab, axises[i] + cube.Index, Quaternion.identity, cube.Obj.transform);
            suf.transform.GetChild(0).rotation = QuaternionsOuter[axises[i]];
            if (!suf.GetComponent<SurfaceController>())
            {
                suf.AddComponent<SurfaceController>();
            }
            CreatDice(suf.GetComponent<SurfaceController>().Data);
        } // 生成面
        if (nearBy.Count > 0)
        {
            for (int i = 0; i < nearBy.Count; i++)
            {
                MapData.Instance.Cubes[nearBy[i]].Surfaces[nearDir[i]].Obj.SetActive(false);
            }
        } // 将相邻方块的重叠面搞了

    }

    /// <summary>
    /// 生成骰子 TODO 将Instantiate改为从对象池取出
    /// </summary>
    /// <param name="suf"></param>
    public void CreatDice(SurfaceData suf)
    {
        List<Vector3> V3_1 = new List<Vector3>();
        List<Vector3> V3_2 = new List<Vector3>();
        List<Vector3> axises = new List<Vector3>(Axises.ToArray());
        for (int i = 0; i < 5; i++)
        {
            if (!RotateBase.AxisJudgement(suf.Index, axises[i]))
            {
                axises.RemoveAt(i + 1);
                axises.RemoveAt(i);
                break;
            }
        } // 排除所在的轴
        V3_1.Add(axises[0]);
        V3_1.Add(Vector3.zero);
        V3_1.Add(axises[1]);
        V3_2.Add(axises[2]);
        V3_2.Add(Vector3.zero);
        V3_2.Add(axises[3]);

        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                Vector3 temp = V3_1[i] + V3_2[j];
                int index = Random.Range(0, 5);
                DicePrefab = Resources.Load("Dice/" + DicePrefabname[index]) as GameObject;
                GameObject dice = Instantiate(DicePrefab, suf.Cube.Index + suf.Index + temp, QuaternionsOuter[suf.Index], suf.Obj.transform);
                if (!dice.GetComponent<DiceController>())
                {
                    dice.AddComponent<DiceController>();
                }
                //MapData.Instance.Registe(dice);
            }
        }
    }
    /// <summary>
    /// 在正面生成物体
    /// </summary>
    /// <param name="dice"></param>
    /// <param name="prefab"></param>
    /// <returns></returns>
    public GameObject SpawnObj(DiceData dice, GameObject prefab)
    {

        Vector3 Toward = dice.GroundTowards;

        if (Dices2Flip.Contains(dice))
        {
            return null;
        }

        if (prefab == null)
        {
            return null;
        }
        GameObject groundObject = prefab;
        {
            GameObject spawnCube = Instantiate(SpawnCube, dice.DiceCoordinate + Toward * 0.5f, QuaternionsOuter[dice.GroundTowards], dice.Obj.transform.GetChild(0));
            spawnCube.transform.GetChild(0).GetComponent<SpawnCube>().SpawnTing = groundObject;
            spawnCube.transform.GetChild(0).GetComponent<SpawnCube>().dice = dice;
            spawnCube.transform.GetChild(0).GetComponent<SpawnCube>().Quan = QuaternionsOuter[dice.GroundTowards];
        }
        return groundObject;
    }

    /// <summary>
    /// 在背面生成物体
    /// </summary>
    /// <param name="dice"></param>
    /// <param name="prefabname"></param>
    /// <returns></returns>
    public GameObject SpawnObj(DiceData dice, string prefabname = null)
    {
        //int index_1 = Random.Range(1, 3);
        //int index_2 = Random.Range(1, 4);
        //List<string> randomArray = (List<string>)Items[index_1];

        Vector3 Toward = dice.GroundTowards;

        if (Dices2Flip.Contains(dice))
        {
            return null;
        }

        Dices2Flip.Add(dice); // 添加进翻面队

        if (prefabname == "null")
        {
            return null;
        }
        GameObject groundObject;
        //GameObject groundObject=Instantiate(Resources.Load(prefabname) as GameObject);    
        if (dice.Surface != null)
        {
            Debug.Log(prefabname);
            groundObject = Instantiate(Resources.Load(prefabname) as GameObject, dice.DiceCoordinate + Toward * 0.5f, QuaternionsInner[dice.Surface.Index], dice.Obj.transform.GetChild(0));
        }
        else
        {
            groundObject = Instantiate(Resources.Load(prefabname) as GameObject, dice.DiceCoordinate + Toward * 0.5f, QuaternionsInner[dice.GroundTowards], dice.Obj.transform.GetChild(0));
        }
        return groundObject;
        //groundObject.transform.position = Parent.transform.position;
        //groundObject.transform.rotation = Parent.transform.rotation;
        //groundObject.transform.parent = Parent.transform;
        //MapData.Instance.Registe(groundObject);
    }

    private void FlipAct()
    {
        if (Dices2Flip.Count > 0)
        {
            StartCoroutine(Flip(Dices2Flip));
        }
    }

    // 列表中按顺序翻
    public IEnumerator Flip(List<DiceData> list)
    {
        foreach (var item in list)
        {
            item.Controller.Flip(); // 翻这个面
            yield return new WaitForSeconds(0.1f);
        }
        list.Clear();
    }
    /// <summary>
    /// 检查能否翻面
    /// </summary>
    /// <returns></returns>
    private bool CheckFlip()
    {
        if (Time2CheckIt)
        {
            if (Dices2Flip.Count > 0) return true;
            foreach (var cube in MapData.Instance.Cubes)
            {
                if (!cube.Value.Controller.CanFlip())
                {
                    return false;
                }
            }
            RegisteFlips(); // 如果可以翻 找到一个surface,添加进Dices2Flip,并生成CrtstalPrefab
        }
        return true;
    }

    /// <summary>
    /// 在玩家所在面的对面生成晶体面
    /// </summary>
    public void RegisteFlips()
    {
        SurfacePlayerAtWhenFlip = PlayerManager.Instance.Data.CoorDinate.Surface;
        Vector3 temp;
        int x = 0, y = 0, z = 0;
        if (SurfacePlayerAtWhenFlip.Index.x.GetHashCode() != 0.GetHashCode()) x = -(int)SurfacePlayerAtWhenFlip.Index.x;
        else if (SurfacePlayerAtWhenFlip.Index.y.GetHashCode() != 0.GetHashCode()) y = -(int)SurfacePlayerAtWhenFlip.Index.y;
        else z = -(int)SurfacePlayerAtWhenFlip.Index.z;
        temp = new Vector3Int(x, y, z);
        SurfacePlayerAtWhenFlip.Cube.Surfaces[temp].Controller.SpawnObj(0.ToString()); // 生成物体
    }

    /// <summary>
    /// TODO  拾取晶体后，除了玩家所在面全部都要翻
    /// </summary>
    public void PickUpCrystal()
    {
        SurfacePlayerAtWhenFlip = PlayerManager.Instance.Data.CoorDinate.Surface;
        foreach (var cube in MapData.Instance.Cubes)
        {
            foreach (var surf in cube.Value.Surfaces)
            {
                if (surf.Value != SurfacePlayerAtWhenFlip)
                {
                    surf.Value.Controller.SpawnObj(); // 生成物体
                }
            }
        }
    }
}
